home *** CD-ROM | disk | FTP | other *** search
/ PCGUIA 117 / PC Guia 117.iso / Software / Utils / Software6 / Product12 / gmail_notifier-0.4.2-fx+mz.xpi / components / nsGMNotifierService.js < prev    next >
Encoding:
Text File  |  2005-02-27  |  22.5 KB  |  723 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is Gmail Notifier code.
  15.  *
  16.  * The Initial Developer of the Original Code is
  17.  * Doron Rosenberg.
  18.  * Portions created by the Initial Developer are Copyright (C) 2004
  19.  * the Initial Developer. All Rights Reserved.
  20.  *
  21.  * Contributor(s):
  22.  *
  23.  * Alternatively, the contents of this file may be used under the terms of
  24.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  25.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  26.  * in which case the provisions of the GPL or the LGPL are applicable instead
  27.  * of those above. If you wish to allow use of your version of this file only
  28.  * under the terms of either the GPL or the LGPL, and not to allow others to
  29.  * use your version of this file under the terms of the MPL, indicate your
  30.  * decision by deleting the provisions above and replace them with the notice
  31.  * and other provisions required by the GPL or the LGPL. If you do not delete
  32.  * the provisions above, a recipient may use your version of this file under
  33.  * the terms of any one of the MPL, the GPL or the LGPL.
  34.  *
  35.  * ***** END LICENSE BLOCK ***** */
  36.  
  37. /*
  38.  todo:
  39.    - array.pop
  40.    - nsITimer should not be a one-shot
  41. */
  42.  
  43. const kGMSERVICE_CONTRACTID = "@mozilla.org/GMailNotifier;1"
  44. const kGMSERVICE_CID = Components.ID("7b69f823-6d18-4c7f-a4e5-c5c2507217b8");
  45. const nsIGMNotifierService = Components.interfaces.nsIGMNotifierService
  46. const nsIGMNotifierProgressListener = Components.interfaces.nsIGMNotifierProgressListener;
  47. const nsISupports = Components.interfaces.nsISupports;
  48.  
  49. const kIOSERVICE_CONTRACTID = "@mozilla.org/network/io-service;1";
  50. const nsIIOService = Components.interfaces.nsIIOService;
  51.  
  52. const nsICookieManager = Components.interfaces.nsICookieManager;
  53. const kCOOKIESERVICE_CONTRACTID = "@mozilla.org/cookieService;1";
  54.  
  55. const kPSWDMANAGER_CONTRACTID = "@mozilla.org/passwordmanager;1";
  56. const nsIPasswordManagerInternal = Components.interfaces.nsIPasswordManagerInternal;
  57.  
  58. const kTIMER_CONTRACTID = "@mozilla.org/timer;1";
  59. const nsITimer = Components.interfaces.nsITimer;
  60.  
  61. // debug output
  62. const GM_DEBUG = false;
  63.  
  64. function nsGMNotifierService() {
  65.   this.listeners = new Array();
  66.   this.updateTimer = null;
  67.  
  68.   this.unreadEmails = null;
  69.   this.resetState = false;
  70.   this.newEmails = 0;
  71.   this.space_used_mb = null;
  72.   this.space_used_percent = null;  
  73.  
  74.   this.connectionPhase = 0;
  75.   this.loggedIn = false;
  76.   
  77.   this.username = null;
  78.   this.password = null;
  79.   
  80.   this.timeOut = 600000; // default to 10 mins
  81.   
  82.   this.prefBranch = null;
  83.   this.stringBundle = null;
  84.   
  85.   this.notificationListenerID;
  86.   
  87.   var myThis = this;
  88.   this.PrefChangeObserver = {
  89.     observe: function(aSubject, aTopic, aData)
  90.     {
  91.       myThis.prefChanged(aData);
  92.     }
  93.   };
  94.  
  95.   this.logString = "";
  96.   
  97.   this.addObserver("gm-notifier", this.PrefChangeObserver);
  98. }
  99.  
  100. /* 
  101.  * 
  102.  * Scriptable interfaces 
  103.  * 
  104.  */
  105.  
  106. // login method
  107. nsGMNotifierService.prototype.initLogin = function (aUsername, aPassword, aListenerID) {
  108.   gGMNotifierService.logItem("initLogin: aListenerID is " + aListenerID);
  109.   gGMNotifierService.username = aUsername;
  110.   gGMNotifierService.password = aPassword;
  111.  
  112.   gGMNotifierService.notificationListenerID = aListenerID;
  113.  
  114.   gGMNotifierService.talkToServer();
  115. }
  116.  
  117. nsGMNotifierService.prototype.checkNow = function () {
  118.   gGMNotifierService.talkToServer();
  119. }
  120.  
  121. nsGMNotifierService.prototype.logout = function () {
  122.   this.username = null;
  123.   this.password = null;
  124.  
  125.   this.unreadEmails = null;
  126.   this.newEmails = 0;
  127.   this.space_used_mb = null;
  128.   this.space_used_percent = null;
  129.  
  130.   if (this.updateTimer)
  131.     this.updateTimer.cancel();
  132.   this.updateTimer = null;
  133.   
  134.   this.loggedIn = false;
  135.  
  136.   //clear the login cookie
  137.   try{
  138.     var ios = Components.classes[kIOSERVICE_CONTRACTID].getService(nsIIOService);
  139.     var cookMan = Components.classes[kCOOKIESERVICE_CONTRACTID].getService(nsICookieManager);
  140.     cookMan.remove("gmail.google.com", "GV", "/", false);
  141.   } catch(e){}
  142.  
  143.   this.pushStateChange(nsIGMNotifierProgressListener.LOGOUT);
  144. }
  145.  
  146. // users can add listeners (nsIGMNotifierListener) here
  147. nsGMNotifierService.prototype.addListener = function(aListener) {
  148.   // should we autologin?
  149.   // make sure to only check for autologin the first time a listener has been 
  150.   // added, ie first browser window calls us.
  151.   if ( (this.listeners.length == 0) && this.prefBranch &&
  152.        this.prefBranch.getBoolPref("gm-notifier.autologin.enabled") ) {
  153.     // autologin
  154.     var defaultUser = this.prefBranch.getCharPref("gm-notifier.users.default");
  155.     if (defaultUser) {
  156.       this.username = defaultUser;
  157.       this.password = this.getLoginDetails(this.username);
  158.       this.talkToServer();
  159.     }
  160.   }
  161.  
  162.   this.listeners.push(aListener);
  163.  
  164.   // for every new listener added, push login state
  165.   if (this.loggedIn)
  166.     aListener.onStateChange(nsIGMNotifierProgressListener.LOGIN_SUCCESS);
  167.   else
  168.     aListener.onStateChange(nsIGMNotifierProgressListener.LOGOUT);
  169.  
  170.   return this.listeners.length;
  171. }
  172.  
  173. nsGMNotifierService.prototype.removeListener = function(aListener) {
  174.   var found = false;
  175.   var run = 0;
  176.   
  177.   while (!found || (run < this.listeners.length)) {
  178.     if (this.listeners[run] == aListener) {
  179.       this.listeners[run] = null;
  180.       found = true;
  181.     }
  182.     run++;  
  183.   }
  184. }
  185.  
  186. nsGMNotifierService.prototype.getUnreadCount = function() {
  187.   if (this.resetState)
  188.     return 0;
  189.   else
  190.     return this.unreadEmails;
  191. }
  192.  
  193. nsGMNotifierService.prototype.getNewCount = function() {
  194.   if (this.resetState)
  195.     return 0;
  196.   else
  197.     return this.newEmails;
  198. }
  199.  
  200. nsGMNotifierService.prototype.getUsedMB = function() {
  201.   return this.space_used_mb;
  202. }
  203.  
  204. nsGMNotifierService.prototype.getSpaceUsed = function() {
  205.   return this.space_used_percent;
  206. }
  207.  
  208. nsGMNotifierService.prototype.getUserName = function() {
  209.   return this.username;
  210. }
  211.  
  212. nsGMNotifierService.prototype.setTimeout = function(aMinutes) {
  213.   // convert to ms
  214.   this.timeOut = (aMinutes * 60000);
  215.  
  216.   // set timer only if we are logged in
  217.   if (this.loggedIn)
  218.     this.setTimer();
  219. }
  220.  
  221. /* 
  222.  * 
  223.  * Non-Scriptable interfaces 
  224.  * 
  225.  */
  226.  
  227. nsGMNotifierService.prototype.pushStateChange = function(aState) {
  228.   for (var run = 0; run < this.listeners.length; run++)
  229.     if (this.listeners[run]) // can be null
  230.       this.listeners[run].onStateChange(aState);
  231. }
  232.  
  233. // timing stuff
  234. nsGMNotifierService.prototype.setTimer = function() {
  235.   if (this.updateTimer) {
  236.     this.updateTimer.cancel();
  237.   } else {
  238.     this.updateTimer = Components.classes[kTIMER_CONTRACTID]
  239.                         .createInstance(nsITimer);
  240.   }
  241.  
  242.   this.updateTimer.initWithCallback(this, this.timeOut, nsITimer.TYPE_ONE_SHOT);
  243. }
  244.  
  245. // nsITimer
  246. nsGMNotifierService.prototype.notify = function(aTimer) {
  247.   this.talkToServer();
  248. }
  249.  
  250. nsGMNotifierService.prototype.observer = function(aCallbackFunc) {
  251.   return ({
  252.     data : "",
  253.    
  254.     onStartRequest : function (aRequest, aContext) {
  255.       this.data = "";
  256.     },
  257.  
  258.     onDataAvailable : function (aRequest, aContext, aStream, aSourceOffset, aLength){
  259.       var scriptableInputStream = 
  260.         Components.classes["@mozilla.org/scriptableinputstream;1"]
  261.           .createInstance(Components.interfaces.nsIScriptableInputStream);
  262.       scriptableInputStream.init(aStream);
  263.  
  264.       this.data += scriptableInputStream.read(aLength);
  265.     },
  266.  
  267.     onStopRequest : function (aRequest, aContext, aStatus) {
  268.       aCallbackFunc(this.data, aRequest);
  269.     },
  270.  
  271.     QueryInterface : function(aIID) {
  272.       if (aIID.equals(Components.interfaces.nsIStreamListener) ||
  273.           aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
  274.           aIID.equals(Components.interfaces.nsIAlertListener) ||
  275.           aIID.equals(nsISupports))
  276.         return this;
  277.       throw Components.results.NS_NOINTERFACE;
  278.     }
  279.   }
  280.   );
  281. }
  282.  
  283. nsGMNotifierService.prototype.start = function (aURL, aPostData, aCookieData, aReferrer, aCallbackFunc){
  284.  
  285.   // the IO service
  286.   var ioService = Components.classes[kIOSERVICE_CONTRACTID].getService(nsIIOService);
  287.       
  288.   // create an nsIURI
  289.   var uri = ioService.newURI(aURL, null, null);
  290.  
  291.   //nsIInputStream
  292.   var uploadStream = Components.classes["@mozilla.org/io/string-input-stream;1"]
  293.     .createInstance(Components.interfaces.nsIStringInputStream);
  294.  
  295.   if (aPostData)
  296.     uploadStream.setData(aPostData, aPostData.length);
  297.  
  298.   // get a channel for that nsIURI
  299.   var channel = ioService.newChannelFromURI(uri);
  300.  
  301.   // get a httpchannel and make it a post
  302.   var httpChannel = channel.QueryInterface(Components.interfaces.nsIHttpChannel);
  303.  
  304.   // set a referrer
  305.   if (aReferrer) {
  306.     var referrerUri = ioService.newURI(aReferrer, null, null);
  307.     httpChannel.referrer = referrerUri;
  308.   }
  309.  
  310.   if (aPostData) {
  311.     var uploadChannel = channel.QueryInterface(Components.interfaces.nsIUploadChannel);
  312.     uploadChannel.setUploadStream(uploadStream, "application/x-www-form-urlencoded", -1);
  313.  
  314.     // order important - setUploadStream resets to get/put
  315.     httpChannel.requestMethod = "POST";
  316.   }
  317.  
  318.   if (aCookieData){
  319.     // httpChannel.setRequestHeader("Cookie", aCookieData, false);
  320.     for (var run = 0; run < aCookieData.length; run++){
  321.       httpChannel.setRequestHeader("Cookie", aCookieData[run], true);
  322.     }
  323.   }
  324.  
  325.   var observer = new this.observer(aCallbackFunc);
  326.   channel.asyncOpen(observer, null);
  327. }
  328.  
  329. // initiates talking to Gmail
  330. nsGMNotifierService.prototype.talkToServer = function () {
  331.  
  332.   if (!this.username || !this.password) {
  333.     return;
  334.   }
  335.  
  336.   this.resetState = false;
  337.  
  338.   this.connectionPhase = 0;
  339.   this.pushStateChange(nsIGMNotifierProgressListener.LOGIN_INITIATED);
  340.  
  341.   var data = "service=mail&Email=" + encodeURIComponent(this.username) 
  342.              + "&Passwd=" + encodeURIComponent(this.password) + 
  343.              "&null=Sign%20in&continue=http://gmail.google.com/gmail";
  344.  
  345.   this.start("https://www.google.com/accounts/ServiceLoginBoxAuth", data, null,
  346.             "https://www.google.com/", this.callback);
  347. }
  348.  
  349. /*
  350.    Phase              Description
  351.    0                  Before anything has happend
  352.    1                  First connection
  353.    ...
  354. */
  355.  
  356. nsGMNotifierService.prototype.callback = function (aData, aRequest) {
  357.   gGMNotifierService.connectionPhase++;
  358.  
  359.   switch (gGMNotifierService.connectionPhase) {
  360.     case 1:
  361.       var cookieData;
  362.  
  363.       // if no cookies sent, an exception is thrown
  364.       try{
  365.         //var httpChannel = aRequest.QueryInterface(Components.interfaces.nsIHttpChannel)
  366.         //cookieData = httpChannel.getRequestHeader("cookie");
  367.       } catch(e){}
  368.  
  369.       var val = aData.match(/="CheckCookie[^]+Html"/);
  370.  
  371.       if (!val) {
  372.         // XXX - check if its an image request
  373.  
  374.         // failed to login
  375.         gGMNotifierService.pushStateChange(nsIGMNotifierProgressListener.LOGIN_FAILED);
  376.         return;
  377.       }
  378.  
  379.       var url =  val[0].substr(2, (val[0].length-3) );
  380.       /* var val = aData.match(/var cookieVal= "([^"]+)";/); */
  381.  
  382.       gGMNotifierService.start("https://www.google.com/accounts/" + url, 
  383.              null, null, "https://www.google.com/", gGMNotifierService.callback);
  384.       break;
  385.  
  386.     case 2:
  387.       var val = aData.match(/replace\("[^]+"/);
  388.  
  389.       if (!val) {
  390.         // failed to login
  391.         gGMNotifierService.pushStateChange(nsIGMNotifierProgressListener.LOGIN_FAILED);
  392.         return;
  393.       }
  394.  
  395.       var url = val[0].substr(9, (val[0].length-1) )
  396.       url = url.substr(0, (url.length-1) );
  397.  
  398.       gGMNotifierService.start(url, null, null, "https://www.google.com/", gGMNotifierService.callback);
  399.       break;
  400.  
  401.     case 3:
  402.       gGMNotifierService.start("https://gmail.google.com/gmail?search=adv&as_subset=unread&view=tl&start=0", 
  403.             null, null, "https://www.google.com/", gGMNotifierService.callback);
  404.       break;
  405.  
  406.     case 4:
  407.       var val = aData.match(/\["ds",.*\]/);
  408.  
  409.       if (!val) {
  410.         var myVal = aData.match(/Captcha\?ctoken.*.com"/);
  411.  
  412.         // failed to login
  413.         gGMNotifierService.pushStateChange(nsIGMNotifierProgressListener.LOGIN_FAILED);
  414.         return;
  415.       }
  416.  
  417.       var myArray = eval(val[0]);
  418.       gGMNotifierService.logItem("GMail new mail check complete:");
  419.       gGMNotifierService.logItem("  ::myArray[1] is " + myArray[1] + " unread is " + gGMNotifierService.unreadEmails);
  420.  
  421.       if ( (gGMNotifierService.unreadEmails != null) && (myArray[1] > gGMNotifierService.unreadEmails)) {
  422.         gGMNotifierService.logItem("  New Unread Mail Found!");
  423.         // new email
  424.         gGMNotifierService.newEmails = (parseInt(myArray[1],10) - gGMNotifierService.unreadEmails);
  425.         gGMNotifierService.pushStateChange(nsIGMNotifierProgressListener.NEW_MAIL);
  426.         gGMNotifierService.newMailNotification(gGMNotifierService.newEmails);
  427.       } else if (gGMNotifierService.unreadEmails == null) {
  428.         // first time
  429.         var unread = parseInt(myArray[1], 10);
  430.         if (unread > 0) {
  431.           gGMNotifierService.logItem("  New Mail Found!");
  432.           gGMNotifierService.newEmails = unread;
  433.           gGMNotifierService.unreadEmails = unread;
  434.           gGMNotifierService.pushStateChange(nsIGMNotifierProgressListener.NEW_MAIL);
  435.           gGMNotifierService.logItem("    -- amount of new mail is " + gGMNotifierService.newEmails);
  436.           gGMNotifierService.logItem("      val[0] is " + val[0]);
  437.           gGMNotifierService.logItem("      myArray[1] is " + myArray[1]);
  438.           gGMNotifierService.newMailNotification(gGMNotifierService.newEmails);
  439.         } else {
  440.           gGMNotifierService.newEmails = 0;
  441.           gGMNotifierService.unreadEmails = 0;
  442.         }
  443.       } else {
  444.         gGMNotifierService.logItem("  No New Unread Mail Found!");
  445.         gGMNotifierService.pushStateChange(nsIGMNotifierProgressListener.NO_NEW_MAIL);
  446.       }
  447.  
  448.       gGMNotifierService.unreadEmails = parseInt(myArray[1],10);
  449.  
  450.       val = aData.match(/\["qu",.*\]/);
  451.       myArray = eval(val[0]);
  452.  
  453.       gGMNotifierService.space_used_mb = myArray[1];
  454.       gGMNotifierService.space_used_percent = myArray[3];
  455.  
  456.       gGMNotifierService.loggedIn = true;
  457.  
  458.       gGMNotifierService.pushStateChange(nsIGMNotifierProgressListener.LOGIN_SUCCESS);
  459.       gGMNotifierService.setTimer();
  460.       break;
  461.   }
  462. }
  463.  
  464. /*
  465.   New mail notification
  466.  */
  467. nsGMNotifierService.prototype.newMailNotification = function (aNewNum){
  468.   this.logItem("New Mail Notification Init:");
  469.  
  470.   var isNotificationEnabled = this.prefBranch.getBoolPref("gm-notifier.ui.notification.enabled");
  471.   this.logItem("  Is System Notification Enabled by user: " + isNotificationEnabled);
  472.  
  473.   if (isNotificationEnabled){
  474.     var msg = this.getFormattedString("NotificationMsg", [aNewNum]);
  475.  
  476.     try {
  477.       var alertService = Components.classes["@mozilla.org/alerts-service;1"]
  478.                                    .getService(Components.interfaces.nsIAlertsService);
  479.       if (alertService) {
  480.         alertService.showAlertNotification("chrome://gm-notifier/content/gm-logo.png",
  481.           this.getString("NotificationMsgTitle"), msg, true, "", this);
  482.         this.logItem("  alertsService success.");
  483.       } else {
  484.        this.logItem("  alertsService failure: could not getService nsIAlertsService");
  485.       }
  486.     } catch(e) {
  487.        this.logItem("  alertsService failure: " + e);
  488.     }
  489.   }
  490.   
  491.   // sound notifications
  492.   var isSoundNotificationsEnabled = this.prefBranch.getBoolPref("gm-notifier.ui.soundnotification.enabled");
  493.   this.logItem("  Is Sound Notification Enabled by user: " + isSoundNotificationsEnabled);
  494.  
  495.   if (isSoundNotificationsEnabled) {  
  496.     var soundUrl = this.prefBranch.getCharPref("gm-notifier.ui.soundnotification.uri");
  497.  
  498.     try {
  499.       var sound = Components.classes["@mozilla.org/sound;1"]
  500.                             .createInstance(Components.interfaces.nsISound);
  501.       if (soundUrl.indexOf("file://") == -1) {
  502.         sound.playSystemSound(soundUrl);
  503.       } else {
  504.         var ioService = Components.classes[kIOSERVICE_CONTRACTID].getService(nsIIOService);
  505.         var url = ioService.newURI(soundURL, null, null);
  506.  
  507.         sound.play(url)
  508.       }
  509.     } catch (e) {
  510.       this.logItem("  Sound playing failed with: "+ e);
  511.     }
  512.   }
  513. }
  514.  
  515. nsGMNotifierService.prototype.getStringBundle = function (){
  516.   if (!this.stringBundle) {
  517.     var strBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"]
  518.                              .createInstance(Components.interfaces.nsIStringBundleService);
  519.  
  520.     this.stringBundle = strBundleService.createBundle("chrome://gm-notifier/locale/gm-notifier.properties");
  521.   }
  522.   
  523.   return this.stringBundle;
  524. }
  525.  
  526. nsGMNotifierService.prototype.getString = function (aName){
  527.   return this.getStringBundle().GetStringFromName(aName);
  528. }
  529.  
  530. nsGMNotifierService.prototype.getFormattedString = function (aName, aStrArray){
  531.   return this.getStringBundle().formatStringFromName(aName, aStrArray, aStrArray.length);
  532. }
  533.  
  534. // nsIObserver
  535. nsGMNotifierService.prototype.observe = function (aSubject, aTopic, aData){
  536.   switch (aTopic) {
  537.     case "alertfinished":
  538.       break;
  539.  
  540.     case "alertclickcallback":
  541.      this.showNotification();
  542.       break;
  543.     }
  544. }
  545.  
  546. // nsIAlertsService - nsIAlertListener was deprecated and replaced with nsIObserver
  547. //                    This is to maintain 1.7 compatability.
  548. nsGMNotifierService.prototype.onAlertFinished = function (aCookie){
  549. }
  550.  
  551. nsGMNotifierService.prototype.onAlertClickCallback = function (aCookie){
  552.   this.showNotification();
  553. }
  554.  
  555. nsGMNotifierService.prototype.showNotification = function (){
  556.   // when the alert callback happens, we want to notify the listener that
  557.   // initiated the server connection that the alert was clicked.
  558.   // Simply pushing a state change to all listeners will result in the
  559.   // infinite window open loop!
  560.   
  561.   this.logItem("Alert Clickback called:");
  562.   this.logItem("  Notification Window is: (" + gGMNotifierService.notificationListenerID + ").");
  563.  
  564.   var run = 0;
  565.   if (gGMNotifierService.notificationListenerID) {
  566.     var done = false;
  567.     while (!done && (run < this.listeners.length)) {
  568.       this.logItem("  Item " + run +  " has id (" + this.listeners[run].getID() + ")");
  569.       if (this.listeners[run] && (this.listeners[run].getID() == this.notificationListenerID))
  570.         done = true;
  571.       else 
  572.         run++;
  573.     }
  574.   } else {
  575.     // fallback
  576.     while ((this.listeners[run] == null) && (run < this.listeners.length))
  577.       run++;
  578.  
  579.     this.logItem("  No notification window found, call listener #" + run);
  580.   }
  581.  
  582.   if (this.listeners[run])
  583.     this.listeners[run].onStateChange(nsIGMNotifierProgressListener.LOAD_GMAIL);
  584. }
  585.  
  586. /*
  587.  *
  588.  *  Preference code
  589.  *
  590.  */
  591.  
  592. nsGMNotifierService.prototype.getPrefBranch = function(){
  593.   if (!this.prefBranch){ 
  594.     this.prefBranch = Components.classes['@mozilla.org/preferences-service;1'];
  595.     this.prefBranch = this.prefBranch.getService();
  596.     this.prefBranch = this.prefBranch.QueryInterface(Components.interfaces.nsIPrefBranch);
  597.   }
  598.   
  599.   return this.prefBranch;
  600. }
  601.  
  602. nsGMNotifierService.prototype.prefChanged = function (aPrefName){
  603.   switch(aPrefName){
  604.     case "gm-notifier.update.interval":
  605.       this.setTimeout(this.prefBranch.getIntPref("gm-notifier.update.interval"));
  606.       break;
  607.   }
  608. }
  609.  
  610. nsGMNotifierService.prototype.addObserver = function(aDomain, aFunction){
  611.   var myPrefs = this.getPrefBranch();
  612.   var prefBranchInternal = myPrefs.QueryInterface(Components.interfaces.nsIPrefBranchInternal);
  613.                                                                                              
  614.   if (prefBranchInternal)
  615.     prefBranchInternal.addObserver(aDomain, aFunction, false);
  616. }
  617.  
  618. nsGMNotifierService.prototype.getLoginDetails = function(aUsername){
  619.   var url = "chrome://gm-notifier/";
  620.  
  621.   var passwordManager = Components.classes[kPSWDMANAGER_CONTRACTID]
  622.                         .createInstance(nsIPasswordManagerInternal);
  623.   var host = {value:""};
  624.   var user =  {value:""};
  625.   var password = {value:""}; 
  626.  
  627.   try {
  628.     passwordManager.findPasswordEntry(url, aUsername, "", host, user, password);
  629.   } catch(e){
  630.   }  
  631.  
  632.   return password.value;
  633. }
  634.  
  635. nsGMNotifierService.prototype.getResetState = function() {
  636.   return this.resetState;
  637. }
  638.  
  639. nsGMNotifierService.prototype.setResetState = function(aResetState) {
  640.   this.resetState = aResetState;
  641.   gGMNotifierService.pushStateChange(nsIGMNotifierProgressListener.LOGIN_SUCCESS);
  642. }
  643.  
  644. nsGMNotifierService.prototype.logItem = function(aLog) {
  645.   this.logString += aLog + "|||";
  646. }
  647.  
  648. nsGMNotifierService.prototype.getLog = function() {
  649.   return this.logString;
  650. }
  651.  
  652. nsGMNotifierService.prototype.test = function() {
  653.   return this.g + " testing " + new Date().toString();
  654. }
  655.  
  656. nsGMNotifierService.prototype.QueryInterface = function(iid) {
  657.   if (!iid.equals(nsIGMNotifierService) &&
  658.       !iid.equals(Components.interfaces.nsIAlertListener) &&
  659.       !iid.equals(Components.interfaces.nsIObserver) &&
  660.       !iid.equals(nsISupports))
  661.     throw Components.results.NS_ERROR_NO_INTERFACE;
  662.   return this;
  663. }
  664.  
  665. var gGMNotifierService = new nsGMNotifierService();
  666.  
  667. /**
  668.  * JS XPCOM component registration goop:
  669.  *
  670.  * We set ourselves up to observe the xpcom-startup category.  This provides
  671.  * us with a starting point.
  672.  */
  673.  
  674. var nsGMNotifierServiceModule = new Object();
  675.  
  676. nsGMNotifierServiceModule.registerSelf = function (compMgr, fileSpec, location, type) {
  677.   compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  678.   compMgr.registerFactoryLocation(kGMSERVICE_CID,
  679.                                   "nsGMNotifierService",
  680.                                   kGMSERVICE_CONTRACTID,
  681.                                   fileSpec, 
  682.                                   location, 
  683.                                   type);
  684. }
  685.  
  686. nsGMNotifierServiceModule.getClassObject = function (compMgr, cid, iid) {
  687.   if (!cid.equals(kGMSERVICE_CID))
  688.     throw Components.results.NS_ERROR_NO_INTERFACE;
  689.  
  690.   if (!iid.equals(Components.interfaces.nsIFactory))
  691.     throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  692.  
  693.   return nsGMNotifierServiceFactory;
  694. }
  695.  
  696. nsGMNotifierServiceModule.canUnload = function (compMgr) {
  697.   // cleanup
  698.   gGMNotifierService.listeners = null;
  699.   if (gGMNotifierService.updateTimer)
  700.     gGMNotifierService.updateTimer.cancel();
  701.   gGMNotifierService.updateTimer = null;
  702.  
  703.   return true;
  704. }
  705.  
  706. var nsGMNotifierServiceFactory = new Object();
  707.  
  708. nsGMNotifierServiceFactory.createInstance = function (outer, iid) {
  709.   if (outer != null)
  710.     throw Components.results.NS_ERROR_NO_AGGREGATION;
  711.  
  712.   if (!iid.equals(nsIGMNotifierService) &&
  713.       !iid.equals(Components.interfaces.nsIAlertListener) &&
  714.       !iid.equals(nsISupports))
  715.     throw Components.results.NS_ERROR_NO_INTERFACE;
  716.  
  717.   return gGMNotifierService;
  718. }
  719.  
  720. function NSGetModule(compMgr, fileSpec) {
  721.   return nsGMNotifierServiceModule;
  722. }
  723.